package com.infosys.setl.fp.demo3;

import org.apache.commons.functor.BinaryFunction;
import org.apache.commons.functor.UnaryFunction;
import org.apache.commons.functor.adapter.RightBoundFunction;
import org.apache.commons.functor.core.Constant;
import org.apache.commons.functor.core.Identity;
import org.apache.commons.functor.core.comparator.Min;
import org.apache.commons.functor.core.composite.CompositeUnaryFunction;
import org.apache.commons.functor.core.composite.UnaryCompositeBinaryFunction;

import com.infosys.setl.fp.demo1.SetlItem;
import com.infosys.setl.fp.demo2.Multiply;

public class TestC {
    public static void main(String[] args) {
        double discountRate = 0.1;
        double taxRate = 0.33;
        double maxDiscount = 30;

        UnaryFunction<Double, Double> calcDiscount = new RightBoundFunction<Double, Double>(new Multiply(), new Double(discountRate));
        //Constant
        Constant<Double> cap = new Constant<Double>(new Double(maxDiscount));

        BinaryFunction<Double, Double, Double> calcActualDiscount
        //calcActualDiscount,表达式合成,二元合成,后两个函数的输出作为二元函数的输入。
        = new UnaryCompositeBinaryFunction<Double, Double, Double>(new Min<Double>(), calcDiscount, cap);
        //BinaryFunctionUnaryFunction这个类适配一个二元仿函数，使它像一元仿函数的接口。
        BinaryFunctionUnaryFunction calcActualDiscountAsUnary
        //假定希望保证商店可以给出的最大折扣有一个最大限度。
        //因此，必须将作为 calcDiscount仿函数计算结果得到的折扣量与 cap 值进行比较，
        //并取最小值作为计算出的折扣价格。
        //result=min(calcDiscount(x),cap(x))
        = new BinaryFunctionUnaryFunction(calcActualDiscount);

        BinaryFunction<Double, Double, Double> calcDiscountedPrice
        //Identity(x)=x。
        = new UnaryCompositeBinaryFunction<Double, Double, Double>(new Subtract(), new Identity<Double>(), calcActualDiscountAsUnary);

        BinaryFunctionUnaryFunction calcDiscountedPriceAsUnary
        //result=identity(x) subtract calcActualDiscountAsUnary(x)
        = new BinaryFunctionUnaryFunction(calcDiscountedPrice);
        //
        UnaryFunction<Double, Double> calcTax = new RightBoundFunction<Double, Double>(new Multiply(), new Double(1 + taxRate));
        //calcNetPrice
        CompositeUnaryFunction<Double, Double> calcNetPrice
        //result=calcTax(calcDiscountedPriceAsUnary(x))
        = new CompositeUnaryFunction<Double, Double>(calcTax).of(calcDiscountedPriceAsUnary);
        //test
        SetlItem item = new SetlItem("item");
        item.setPrice(350);
        Double netPrice = calcNetPrice.evaluate(new Double(item.getPrice()));
        System.out.println("The net price is: " + netPrice);
    }
}
